package cn.wlinker.video.monitor.brand.hikversion.create;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import cn.wlinker.video.monitor.brand.hikversion.dto.EZOpenDeviceModel;
import cn.wlinker.video.monitor.brand.hikversion.enums.EZOpenRequestEnum;
import cn.wlinker.video.monitor.brand.hikversion.utils.EZOpenRequestUtils;
import cn.wlinker.video.monitor.constant.CommonConstant;
import cn.wlinker.video.monitor.domain.Page;
import cn.wlinker.video.monitor.domain.PageQuery;
import cn.wlinker.video.monitor.domain.dto.MonitorDeviceDTO;
import cn.wlinker.video.monitor.domain.dto.PlayUrlDTO;
import cn.wlinker.video.monitor.domain.vo.MonitorDeviceVO;
import cn.wlinker.video.monitor.domain.vo.PictureUrlVO;
import cn.wlinker.video.monitor.domain.vo.PresetAddVO;
import cn.wlinker.video.monitor.domain.vo.VideoVO;
import cn.wlinker.video.monitor.service.IVideoStreamService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 萤石云构建视频流
 *
 * @author gxsjx
 * @version 1.0
 * @date 2022/7/26
 */
@Slf4j
@Service
public class EZOpenStreamServiceImpl implements IVideoStreamService {

    @Override
    public JSONObject capacity(MonitorDeviceDTO dto) {
        Map<String, Object> params = EZOpenRequestUtils.initParamMapWithToken(dto);
        params.put("deviceSerial", dto.getDeviceCode());
        Optional<JSONObject> jsonObject = EZOpenRequestEnum.CAPACITY.requestAndGetData(params);
        return jsonObject.orElse(null);
    }

    @Override
    public Boolean ptzStart(MonitorDeviceDTO monitorDeviceDTO, Integer direction, Integer speed) {
        Map<String, Object> params = EZOpenRequestUtils.initParamMapWithToken(monitorDeviceDTO);
        params.put("direction", direction);
        params.put("speed", speed);
        Optional<JSONObject> jsonObject = EZOpenRequestEnum.PTZ_START.requestAndGetData(params);
        ThreadUtil.execute(() -> {
            try {
                Thread.sleep(CommonConstant.SINGLE_MOVEMENT_TIME);
            } catch (InterruptedException e) {
                log.error("开始云台转动异常", e);
            }
            ptzStop(monitorDeviceDTO, direction);
        });
        return jsonObject.isPresent();
    }

    @Override
    public Boolean ptzStop(MonitorDeviceDTO monitorDeviceDTO, Integer direction) {
        Map<String, Object> params = EZOpenRequestUtils.initParamMapWithToken(monitorDeviceDTO);
        params.put("direction", direction);
        Optional<JSONObject> jsonObject = EZOpenRequestEnum.PTZ_STOP.requestAndGetData(params);
        return jsonObject.isPresent();
    }

    @Override
    public VideoVO buildVideoStream(MonitorDeviceDTO dto, PlayUrlDTO playUrlDTO) {
        EZOpenRequestUtils.autoCloseLive(dto);
        VideoVO vo = new VideoVO();
        vo.setName(dto.getName());
        Map<String, Object> params = EZOpenRequestUtils.initParamMapWithToken(dto);
        Map<String, Object> stringObjectMap = BeanUtil.beanToMap(playUrlDTO);
        stringObjectMap.remove("id");
        params.putAll(stringObjectMap);
        Optional<JSONObject> jsonObject = EZOpenRequestEnum.GET_STREAM.requestAndGetData(params);
        if (jsonObject.isPresent()) {
            JSONObject data = jsonObject.get();
            String url = (String) data.get("url");
            Object expireTimeObj = data.get("expireTime");
            DateTime expireTime = DateUtil.parse(expireTimeObj.toString());
            vo.setPlayUrl(url);
            vo.setExpireTime(expireTime);
        }
        return vo;
    }

    @Override
    public Page<MonitorDeviceVO> getMonitorDeviceList(String deviceCode, String status, PageQuery pageQuery) {
        Map<String, Object> params = EZOpenRequestUtils.initParamMapWithToken();
        params.put("pageStart", pageQuery.getPageNum() - 1);
        params.put("pageSize", pageQuery.getPageSize());
        params.put("status", status);
        Optional<JSONObject> sendRequestAndReturnPage = EZOpenRequestEnum.DEVICE_LIST.requestAndGetAll(params);
        Page<MonitorDeviceVO> build = pageQuery.build();
        if (sendRequestAndReturnPage.isPresent()) {
            JSONObject jsonObject = sendRequestAndReturnPage.get();
            JSONArray data = jsonObject.get("data", JSONArray.class);
            JSONObject pageObj = jsonObject.get("page", JSONObject.class);
            List<EZOpenDeviceModel> ezOpenDeviceModels = JSONUtil.toList(data, EZOpenDeviceModel.class);
            List<MonitorDeviceVO> collect = ezOpenDeviceModels.stream().map(t -> {
                MonitorDeviceVO monitorDeviceVO = new MonitorDeviceVO();
                monitorDeviceVO.setName(t.getDeviceName());
                monitorDeviceVO.setStatus(t.getDeviceStatus().getStatus());
                monitorDeviceVO.setDeviceCode(t.getDeviceSerial());
                monitorDeviceVO.setName(t.getDeviceName());
                monitorDeviceVO.setCameraType(t.getDeviceType());
                monitorDeviceVO.setIp(t.getNetAddress());
                monitorDeviceVO.setDeviceVersion(t.getDeviceVersion());
                return monitorDeviceVO;
            }).collect(Collectors.toList());
            build.setRecords(collect);
            build.setTotal(pageObj.get("total", Integer.class));
            build.setSize(pageObj.get("size", Integer.class));
            Integer page = pageObj.get("page", Integer.class);
            Integer current = Optional.ofNullable(page).orElse(1);
            build.setCurrent(current);
            return build;
        }
        return build;
    }

    @Override
    public PictureUrlVO capture(MonitorDeviceDTO dto, Integer quality) {
        Map<String, Object> params = EZOpenRequestUtils.initParamMapWithToken(dto);
        params.put("quality", quality);
        Optional<JSONObject> jsonObject = EZOpenRequestEnum.CAPTURE.requestAndGetData(params);
        if (jsonObject.isPresent()) {
            JSONObject data = jsonObject.get();
            return JSONUtil.toBean(data.toString(), PictureUrlVO.class);
        }
        throw new RuntimeException("抓拍失败");
    }

    @Override
    public PresetAddVO presetAdd(MonitorDeviceDTO monitorDeviceDTO, Integer index) {
        Map<String, Object> params = EZOpenRequestUtils.initParamMapWithToken(monitorDeviceDTO);
        Optional<JSONObject> jsonObject = EZOpenRequestEnum.PRESET_ADD.requestAndGetData(params);
        if (jsonObject.isPresent()) {
            JSONObject data = jsonObject.get();
            return JSONUtil.toBean(data.toString(), PresetAddVO.class);
        }
        throw new RuntimeException("设置预置点失败");
    }

    @Override
    public Boolean presetMove(MonitorDeviceDTO monitorDeviceDTO, Integer index) {
        Map<String, Object> params = EZOpenRequestUtils.initParamMapWithToken(monitorDeviceDTO);
        params.put("index", index);
        Optional<JSONObject> jsonObject = EZOpenRequestEnum.PRESET_MOVE.requestAndGetData(params);
        return jsonObject.isPresent();
    }

    @Override
    public Boolean presetClear(MonitorDeviceDTO monitorDeviceDTO, Integer index) {
        Map<String, Object> params = EZOpenRequestUtils.initParamMapWithToken(monitorDeviceDTO);
        params.put("index", index);
        Optional<JSONObject> jsonObject = EZOpenRequestEnum.PRESET_CLEAR.requestAndGetData(params);
        return jsonObject.isPresent();
    }
}
